#include "GlobalHead.h"
#include "ToolsCallback_Curve.h"
#include "CustomPlayer.h"
#include "part/Part2DObject.h"
#include "App_Application.h"
using namespace Gui;
using namespace Part;
TYPESYSTEM_SOURCE(lineTool,Tools)

lineTool::lineTool(void)
:Tools("lineTool"),toolState(false),mElapseTime(0),currentCam(NULL)
{
 	mInput = CCustomPlayer::Instance().GetInputManager();
 	m_time = CCustomPlayer::Instance().GetTimeManager();
 
 	mRct = CCustomPlayer::Instance().GetRenderContext();
 	currentCam =mRct->GetAttachedCamera();

	pathtype = NO_CIRCLE;
}

lineTool::~lineTool(void)
{
}

CKBOOL lineTool::PointPosition(VxVector& intersect,Vx2DVector pos2D)
{
	VxVector pos3D; 
	mRct->ScreenToViewpoint(pos2D,&pos3D);
	currentCam->Transform(&pos3D,&pos3D);

	VxVector originPos;
	//CKCamera* cam = mRct->GetAttachedCamera();
	//VxVector dir,up;
	//cam->GetOrientation(&dir,&up);
	//if(dir == VxVector::axisZ() && up == VxVector::axisY())
	// return FALSE;
	currentCam->GetPosition(&originPos);
	VxRay ray(originPos,pos3D);

	float dd;
	if(originPos.y<=0)
		dd = originPos.y - 5.0f;
	else
		dd = 0;
	VxVector planeOri(0,dd,0);
	VxVector planeNormal(0.0,1.0,0.0);
	VxPlane plane(planeNormal,planeOri);

	//VxVector intersect;
	float dist;
	BOOL bl = VxIntersect::RayPlane(ray,plane,intersect,dist);

	return TRUE;
}

CKBOOL lineTool::action(CKRenderContext* dev)
{

	if(CCustomPlayer::Instance().GetCurrentInputState() == FALSE)
	{
		return 0;
	}

	Vx2DVector oldMousePos;
	oldMousePos = vMousePos;

	Vx2DVector mousePos;

	mInput->GetMousePosition(mousePos,TRUE);
	vMousePos = mousePos;



	VxVector v3;
	mInput->GetMouseRelativePosition(v3);

	float wheelDir = v3.z;


	CKBOOL left_old, left_new;  // we handle the left mouse button
	left_old= bLeft;

	left_new = mInput->IsMouseButtonDown(CK_MOUSEBUTTON_LEFT);
	bLeft = left_new;




	CKBOOL middle_old, middle_new;  // we handle the middle mouse button

	middle_old = bMiddle;
	middle_new = mInput->IsMouseButtonDown(CK_MOUSEBUTTON_MIDDLE);
	bMiddle = middle_new;


	CKBOOL right_old, right_new;  // we handle the right mouse button

	right_old = bRight;
	right_new = mInput->IsMouseButtonDown(CK_MOUSEBUTTON_RIGHT);
	bRight = right_new;



	//double click, get delta time
	int dblClkSpeed = 500;

	int deltaTime = mElapseTime;

	int oldDT=deltaTime;
	if (deltaTime!=-1 && (int)(deltaTime & 0x3fffffff)>=0)
		deltaTime = (int)(deltaTime & 0x3fffffff) + (int)m_time->GetLastDeltaTime() + (deltaTime & 0xc0000000) ;

	bool press = false;
	CKBYTE mousesState[4];
	mInput->GetMouseButtonsState(mousesState);
	for (int i = 0; i < 3 ; ++i)
	{
		if((mousesState[i]) == KEY_PRESSED)
		{
			press = true;
			break;
		}
	}

	//left button down
	//////////////////////////////////////////////////////////////////////////
	if( !left_old && left_new) 
	{
		VxVector interPosition;
		if(PointPosition(interPosition,mousePos))
		{
			addCurvePoint(interPosition);

		}
	}
	//left buuton up
	if( left_old && !left_new) {

	}

	//}
	//right button down
	//////////////////////////////////////////////////////////////////////////    
	if( !right_old && right_new) {
		Part::Part2DObject* p2d = static_cast<Part::Part2DObject*>(pDocumentObject);
		p2d->setCurvePointCollection();
		removeCallBack(this);
	}
	//right button up
	if( right_old && !right_new) {



	}
	//Middle Button down
		////////////////////////////////////////////////////////////////////////
		if( !middle_old && middle_new) {



		}
		//Midlle button up
		if( middle_old && !middle_new) {



		}


		// left db1 click
		////////////////////////////////////////////////////////////////////////
		if((!left_old && left_new) )
		{
			if (deltaTime==-1 || (deltaTime & 0xc0000000) != 0)//bit flag is not 0<=>left
				deltaTime=0;
			else if ((int)(deltaTime & 0x3fffffff)<=dblClkSpeed)
			{
				deltaTime=-1;

				int pointCont = pCurve->GetControlPointCount();
				if(pointCont<=1)
				{
					//GetApp_Application().getActiveDocument()->remObject(pObject->getNameInDocument());
				}

			}
		}
		//right dbl click
			if((!right_old && right_new))
			{
				if (deltaTime==-1 || (deltaTime & 0xc0000000) != 0x40000000)//bit flag is not 01<=>right
					deltaTime= 0 + (1<<30);
				else if ((int)(deltaTime & 0x3fffffff)<=dblClkSpeed)
				{
					deltaTime=-1;

					//oneactive = TRUE;
				}
			}
			//middle dbl click
				////////////////////////////////////////////////////////////////////////		
				if((!middle_old && middle_new))
				{
					if (deltaTime==-1 || (deltaTime & 0xc0000000) != 0x80000000)//bit flag is not 10<=>middle
						deltaTime=0 + (1<<31);
					else if ((int)(deltaTime & 0x3fffffff)<=dblClkSpeed)
					{
						deltaTime=-1;

						//oneactive = TRUE;
					}
				}

				//double click delta time storage
					if (deltaTime != -1)
						if ((int)(deltaTime & 0x3fffffff)>dblClkSpeed)
							deltaTime=-1;
				if(oldDT != deltaTime)
					mElapseTime = deltaTime;



				return true;
}
void lineTool::addCurvePoint(VxVector& pos)
{
	std::string pn = "Point_";
	int count = pCurve->GetControlPointCount();
	char buf[16];
	sprintf(buf,"%d",count);
	pn+= buf;
	CKCurvePoint* cpt = CCustomPlayer::Instance().createCurvePoint(pn.c_str());
	cpt->SetPosition(&pos);
	pCurve->AddControlPoint(cpt);
}

CKCurve* lineTool::addCurve(VxVector& pos01,VxVector& pos02,VxVector& pos03)
{

	CKCurve* pcurve;

	return pcurve;
}
void lineTool::setState(bool bl)
{
	toolState = bl;
}
void lineTool::addCallBack(Tools* tl)
{
	CKCamera* cam = mRct->GetAttachedCamera();
	VxVector dir,up;
	cam->GetOrientation(&dir,&up);
	if(dir == VxVector::axisZ() && up == VxVector::axisY())
		return ;
	if(pDocumentObject == NULL)
		return;

	Part::Part2DObject* curve = static_cast<Part::Part2DObject*>(pDocumentObject);
	if(curve)
		pCurve = static_cast<CKCurve*>(curve->Shape.getValue());


	Tools::addCallBack(tl);

}
void lineTool::onChanged(const App::Property* prop)
{
	int a = 0;
}
void lineTool::removeCallBack(Tools* tl)
{

	if(pCurve->GetControlPointCount()<=1)
	{
		GetApp_Application().getActiveDocument()->remObject(pDocumentObject->getNameInDocument());
	}

	Tools::removeCallBack(tl);
}




//////////////////////////////////////////////////////////////////////////
TYPESYSTEM_SOURCE(CircleTool,Tools)

CircleTool::CircleTool():Tools("CircleTool"),toolState(false),mElapseTime(0),currentCam(NULL)
{
	mInput = CCustomPlayer::Instance().GetInputManager();
	m_time = CCustomPlayer::Instance().GetTimeManager();

	mRct = CCustomPlayer::Instance().GetRenderContext();
	currentCam =mRct->GetAttachedCamera();

	changeRadius = false;

	pathtype = CIRCLE;
}
CircleTool::~CircleTool()
{

}

CKBOOL CircleTool::action(CKRenderContext* dev)
{

	if(CCustomPlayer::Instance().GetCurrentInputState() == FALSE)
	{
		return 0;
	}

	Vx2DVector oldMousePos;
	oldMousePos = vMousePos;

	Vx2DVector mousePos;

	mInput->GetMousePosition(mousePos,TRUE);
	vMousePos = mousePos;



	VxVector v3;
	mInput->GetMouseRelativePosition(v3);

	float wheelDir = v3.z;


	CKBOOL left_old, left_new;  // we handle the left mouse button
	left_old= bLeft;

	left_new = mInput->IsMouseButtonDown(CK_MOUSEBUTTON_LEFT);
	bLeft = left_new;




	CKBOOL middle_old, middle_new;  // we handle the middle mouse button

	middle_old = bMiddle;
	middle_new = mInput->IsMouseButtonDown(CK_MOUSEBUTTON_MIDDLE);
	bMiddle = middle_new;


	CKBOOL right_old, right_new;  // we handle the right mouse button

	right_old = bRight;
	right_new = mInput->IsMouseButtonDown(CK_MOUSEBUTTON_RIGHT);
	bRight = right_new;



	//double click, get delta time
	int dblClkSpeed = 500;

	int deltaTime = mElapseTime;

	int oldDT=deltaTime;
	if (deltaTime!=-1 && (int)(deltaTime & 0x3fffffff)>=0)
		deltaTime = (int)(deltaTime & 0x3fffffff) + (int)m_time->GetLastDeltaTime() + (deltaTime & 0xc0000000) ;

	bool press = false;
	CKBYTE mousesState[4];
	mInput->GetMouseButtonsState(mousesState);
	for (int i = 0; i < 3 ; ++i)
	{
		if((mousesState[i]) == KEY_PRESSED)
		{
			press = true;
			break;
		}
	}
	
	//left button down
	//////////////////////////////////////////////////////////////////////////
	if( !left_old && left_new) 
	{
		
		if(PointPosition(interPosition,mousePos))
		{
			createCircel(0,interPosition);
			changeRadius = true;
			originCircle = interPosition;
		}

	}

	VxVector cursorPos;

	mInput->GetMouseRelativePosition(cursorPos);

	if (/*(int)cursorPos.x != 0 || (int)cursorPos.y != 0 && */changeRadius)
	{
		VxVector tempDistans = interPosition - getCurIntersectPlane(mousePos);
		float tempRadius = tempDistans.Magnitude();

		char str[128];
		sprintf(str,"tempRadius:%f",tempRadius);
		OutputDebugString(str);

		createCircel(tempRadius,interPosition);
	}

	//left buuton up
	if( left_old && !left_new) {

         
	}
	
	//}
	//right button down
	//////////////////////////////////////////////////////////////////////////    
	if( !right_old && right_new) {
		
		Part::Part2DObject* p2d = static_cast<Part::Part2DObject*>(pDocumentObject);
		p2d->setCurvePointCollection();
		removeCallBack(this);

		changeRadius = false;
	}
	//right button up
	if( right_old && !right_new) {



	}
	//Middle Button down
	////////////////////////////////////////////////////////////////////////
	if( !middle_old && middle_new) {

	}
	//Midlle button up
	if( middle_old && !middle_new) {



	}


	// left db1 click
	////////////////////////////////////////////////////////////////////////
	if((!left_old && left_new) )
	{
		if (deltaTime==-1 || (deltaTime & 0xc0000000) != 0)//bit flag is not 0<=>left
			deltaTime=0;
		else if ((int)(deltaTime & 0x3fffffff)<=dblClkSpeed)
		{
			deltaTime=-1;

			int pointCont = pCurve->GetControlPointCount();
			if(pointCont<=1)
			{
				//GetApp_Application().getActiveDocument()->remObject(pObject->getNameInDocument());
			}

		}
	}
	//right dbl click
	if((!right_old && right_new))
	{
		if (deltaTime==-1 || (deltaTime & 0xc0000000) != 0x40000000)//bit flag is not 01<=>right
			deltaTime= 0 + (1<<30);
		else if ((int)(deltaTime & 0x3fffffff)<=dblClkSpeed)
		{
			deltaTime=-1;

			//oneactive = TRUE;
		}
	}
	//middle dbl click
	////////////////////////////////////////////////////////////////////////		
	if((!middle_old && middle_new))
	{
		if (deltaTime==-1 || (deltaTime & 0xc0000000) != 0x80000000)//bit flag is not 10<=>middle
			deltaTime=0 + (1<<31);
		else if ((int)(deltaTime & 0x3fffffff)<=dblClkSpeed)
		{
			deltaTime=-1;

			//oneactive = TRUE;
		}
	}

	//double click delta time storage
	if (deltaTime != -1)
		if ((int)(deltaTime & 0x3fffffff)>dblClkSpeed)
			deltaTime=-1;
	if(oldDT != deltaTime)
		mElapseTime = deltaTime;



	return true;
}

void CircleTool::createCircel(float radius,VxVector pos)
{
	pCurve->RemoveAllControlPoints();

	float angle = 0.0f;
	int count = 32;
	float step = 2.0f*PI / count;
	VxVector v(pos);
	int i;
    int start = 0;
	for(i=start;i<start+count;i++) 
	{
		
		v.x = radius*cosf(angle)+pos.x;
		v.z = radius*sinf(angle)+pos.z;
			
		std::string pn = "Point_";
		int count = pCurve->GetControlPointCount();
		char buf[16];
		sprintf(buf,"%d",count);
		pn+= buf;
		CKCurvePoint* cpt = CCustomPlayer::Instance().createCurvePoint(pn.c_str());
		cpt->SetPosition(&v);
		pCurve->AddControlPoint(cpt);
		
		angle += step;
	}

	pCurve->Close();
}

CKCurve* CircleTool::addCurve(VxVector& pos01,VxVector& pos02,VxVector& pos03)
{

	CKCurve* pcurve;

	return pcurve;
}
void CircleTool::addCurvePoint(VxVector& pos)
{
	std::string pn = "Point_";
	int count = pCurve->GetControlPointCount();
	char buf[16];
	sprintf(buf,"%d",count);
	pn+= buf;
	CKCurvePoint* cpt = CCustomPlayer::Instance().createCurvePoint(pn.c_str());
	cpt->SetPosition(&pos);
	pCurve->AddControlPoint(cpt);
}
void CircleTool::setState(bool bl)
{
	toolState = bl;
}

void CircleTool::addCallBack(Tools* tl)
{
	CKCamera* cam = mRct->GetAttachedCamera();
	VxVector dir,up;
	cam->GetOrientation(&dir,&up);
	if(dir == VxVector::axisZ() && up == VxVector::axisY())
		return ;
	if(pDocumentObject == NULL)
		return;

	Part::Part2DObject* curve = static_cast<Part::Part2DObject*>(pDocumentObject);
	if(curve)
		pCurve = static_cast<CKCurve*>(curve->Shape.getValue());


	Tools::addCallBack(tl);

}
void CircleTool::onChanged(const App::Property* prop)
{
	int a = 0;
}
void CircleTool::removeCallBack(Tools* tl)
{

	if(pCurve->GetControlPointCount()<=1)
	{
		GetApp_Application().getActiveDocument()->remObject(pDocumentObject->getNameInDocument());
	}

	Tools::removeCallBack(tl);
}

CKBOOL CircleTool::PointPosition(VxVector& intersect,Vx2DVector pos2D)
{
	VxVector pos3D; 
	mRct->ScreenToViewpoint(pos2D,&pos3D);
	currentCam->Transform(&pos3D,&pos3D);

	VxVector originPos;
	//CKCamera* cam = mRct->GetAttachedCamera();
	//VxVector dir,up;
	//cam->GetOrientation(&dir,&up);
	//if(dir == VxVector::axisZ() && up == VxVector::axisY())
	// return FALSE;
	currentCam->GetPosition(&originPos);
	VxRay ray(originPos,pos3D);

	float dd;
	if(originPos.y<=0)
		dd = originPos.y - 5.0f;
	else
		dd = 0;
	VxVector planeOri(0,dd,0);
	VxVector planeNormal(0.0,1.0,0.0);
	VxPlane plane(planeNormal,planeOri);

	//VxVector intersect;
	float dist;
	BOOL bl = VxIntersect::RayPlane(ray,plane,intersect,dist);

	return TRUE;
}

VxVector CircleTool::getCurIntersectPlane(Vx2DVector pos2D)
{
	VxVector pos3D; 
	mRct->ScreenToViewpoint(pos2D,&pos3D);
	currentCam->Transform(&pos3D,&pos3D);

	VxVector originPos;
	//CKCamera* cam = mRct->GetAttachedCamera();
	//VxVector dir,up;
	//cam->GetOrientation(&dir,&up);
	//if(dir == VxVector::axisZ() && up == VxVector::axisY())
	// return FALSE;
	currentCam->GetPosition(&originPos);
	VxRay ray(originPos,pos3D);

	float dd;
	if(originPos.y<=0)
		dd = originPos.y - 5.0f;
	else
		dd = 0;
	VxVector planeOri(0,dd,0);
	VxVector planeNormal(0.0,1.0,0.0);
	VxPlane plane(planeNormal,planeOri);

	VxVector intersect;
	float dist;
	BOOL bl = VxIntersect::RayPlane(ray,plane,intersect,dist);

	return intersect;
}